using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Logic;
using Habanero.BO;
using Habanero.Testability;
using NUnit.Framework;
using Rhino.Mocks;

namespace Firestarter.DB.Schema.Test.Logic
{
    [TestFixture]
    public class TestDBSchemaExtractor_MySQL_GetSchemaConfigDataForMySQL
    {
        [Test]
        public void Test_CatalogName_ShouldReturnNullForMySQL()
        {
            //---------------Set up test pack-------------------
            var dbConnection = MockRepository.GenerateStub<IDbConnection>();
            dbConnection.Stub(connection => connection.Database).Return(RandomValueGen.GetRandomString());
            var dbSchemaExtractor = new DBSchemaExtractorMySQL(dbConnection);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dbConnection.Database);
            //---------------Execute Test ----------------------
            string catalogName = dbSchemaExtractor.CatalogName;
            //---------------Test Result -----------------------
            Assert.IsNull(catalogName);
        }
        [Test]
        public void Test_SchemaName_ShouldReturnDatabaseNameForMySQL()
        {
            //---------------Set up test pack-------------------
            var dbConnection = MockRepository.GenerateStub<IDbConnection>();
            string expectedDBName = RandomValueGen.GetRandomString();
            dbConnection.Stub(connection => connection.Database).Return(expectedDBName);
            var dbSchemaExtractor = new DBSchemaExtractorMySQL(dbConnection);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dbConnection.Database);
            //---------------Execute Test ----------------------
            string schemaNameName = dbSchemaExtractor.SchemaName;
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedDBName.ToLowerInvariant(), schemaNameName);
        }
    }
    [TestFixture]
    public class TestDBSchemaExtractor
    {
        private SchemaTestPack _testPack;
        private TestUtilsDB _testUtilsDb;
        private IDbConnection _connection;
        private int _testnum = 0;

        [TestFixtureSetUp]
        public virtual void SetupFixture()
        {
            TestUtilsDBSchema.LoadClassDefs();
            BORegistry.DataAccessor = new DataAccessorInMemory();

        }
        [SetUp]
        public virtual void SetupTest()
        {
            _testUtilsDb = CreateSchemaTestDbUtil();
            _testUtilsDb.TestDatabaseName = _testUtilsDb.TestDatabaseName + _testnum++;

            _testUtilsDb.CreateTestDatabase();
            _connection = _testUtilsDb.CreateTestDBConnection();
            _testPack = _testUtilsDb.CreateSchemaTestPack();
             
        }

        [TearDown]
        public virtual void TearDown()
        {
            if (_connection != null)
            {
                _connection.Close();
                _connection.Dispose();
                _connection = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

            if (_testUtilsDb != null) { _testUtilsDb.DropDatabase(); }
            
        }

        protected virtual TestUtilsDB CreateSchemaTestDbUtil()
        {
            return new TestUtilsDB_MySql();
        }

        protected DBSchemaExtractor CreateDBSchemaExtractor()
        {
           return CreateDBSchemaExtractor(_connection);
        }

        protected virtual DBSchemaExtractor CreateDBSchemaExtractor(IDbConnection connection)
        {
            return new DBSchemaExtractorMySQL(connection);
        }

        protected virtual void DropTable(IDbConnection connection, string tableName)
        {
            TestUtilsDBSchema.ExecuteSql(connection, "DROP TABLE IF EXISTS " + tableName);
        }

        public class TestDBSchemaExtractor_SQLServer : TestDBSchemaExtractor
        {
            protected override TestUtilsDB CreateSchemaTestDbUtil()
            {
                return new TestUtilsDB_SqlServer();
            }

            //TODO: Mark 19 jan 2009 - Need to look into limiting Table SQL: WHERE TABLE_TYPE = 'BASE TABLE' AND OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 'IsMsShipped') = 0
            protected override DBSchemaExtractor CreateDBSchemaExtractor(IDbConnection connection)
            {
                return new DBSchemaExtractorSQLServer(connection);
            }

            //protected override CreateTableSqlBuilder_MySql CreateSqlBuilderCreateTable(string tableName)
            //{
            //    return new CreateTableSqlBuilder_SqlServer(tableName);
            //}

            protected override void DropTable(IDbConnection connection, string tableName)
            {
                try
                {
                    TestUtilsDBSchema.ExecuteSql(connection, " DROP TABLE " + tableName);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }

            //protected override CreateTableSqlBuilder_MySql GetSqlBuilderCreateTable(Table referencedTableInfo)
            //{
            //    return new CreateTableSqlBuilder_SqlServer(referencedTableInfo.TableName);
            //}
        }

        //protected override void SetupTestDataBase()
        //{
        //    base.SetupTestDataBase();
        //    CreateTestPackTables();
        //}
        [Test]
        public void Test_CatalogName_ShouldReturnDatabaseName()
        {
            //---------------Set up test pack-------------------
            var dbConnection = MockRepository.GenerateStub<IDbConnection>();
            var expectedDatabaseName = GetRandomString();
            dbConnection.Stub(connection => connection.Database).Return(expectedDatabaseName);
            IDBSchemaExtractor databaseExtractor = new DBSchemaExtractorStub(dbConnection);
            //---------------Assert Precondition----------------
            Assert.AreEqual(expectedDatabaseName, dbConnection.Database);
            //---------------Execute Test ----------------------
            var actualCatalogName = databaseExtractor.CatalogName;
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedDatabaseName, actualCatalogName);
        }


        #region Utils

        //private void CreateTestPackTables()
        //{
        //    IDbConnection connection = CreateTestDBConnection();
        //    DatabaseScriptCreator databaseScriptCreator = new DatabaseScriptCreator();

        //    Table tableInfo = new Table { TableName = "TestTable" };
        //    tableInfo.PrimaryKey = new DBPrimaryKey();
        //    Column pkColumn = new Column("IDColumn") { DataType = "CHAR(38)" };
        //    tableInfo.Columns.Add(pkColumn);
        //    tableInfo.PrimaryKey.PrimaryKeyColumns.Add(new DBPrimaryKeyColumn { Column = pkColumn });
        //    tableInfo.Columns.Add(new Column("TestColumn") { DataType = "VARCHAR(50)" });
        //    Column fkColumn = new Column("FKColumn") { DataType = "VARCHAR(50)" };
        //    tableInfo.Columns.Add(fkColumn);

        //    Table referencedTableInfo = new Table("RefTable") { PrimaryKey = new DBPrimaryKey() };
        //    Column referencedPkColumn = new Column("IDColumn") { DataType = "CHAR(38)" };
        //    referencedTableInfo.Columns.Add(referencedPkColumn);
        //    referencedTableInfo.PrimaryKey.PrimaryKeyColumns.Add(new DBPrimaryKeyColumn { Column = referencedPkColumn });

        //    DBForeignKey foreignKeyInfo = new DBForeignKey
        //    {
        //        ForeignKeyName = "ForeignKey",
        //        ParentTable = tableInfo,
        //        RelatedTable = referencedTableInfo
        //    };
        //    foreignKeyInfo.ForeignKeyColumns.Add(new DBForeignKeyColumn { ParentColumn = fkColumn, RelatedColumn = referencedPkColumn });


        //    ExecuteSql(connection, "DROP TABLE IF EXISTS " + tableInfo.TableName);
        //    ExecuteSql(connection, databaseScriptCreator.CreateTable(tableInfo));
        //    ExecuteSql(connection, databaseScriptCreator.CreateTable(referencedTableInfo));
        //    ExecuteSql(connection, databaseScriptCreator.CreateForeignKey(foreignKeyInfo));
        //}

//        protected virtual void CreateTestPackTables()
//        {
//            IDbConnection connection = CreateTestDBConnection();
//            DatabaseScriptCreator databaseScriptCreator = new DatabaseScriptCreator();

//            Table tableInfo = CreateTableInfo();

//            string sql = databaseScriptCreator.CreateTable(tableInfo, CreateSqlBuilderCreateTable(tableInfo.TableName));
////            ExecuteSql(connection, "DROP TABLE IF EXISTS " + tableInfo.TableName);
//            DropTable(connection, tableInfo.TableName);
//            _testUtilsDb.ExecuteSql(connection, sql);
//        }

//        protected virtual CreateTableSqlBuilder_MySql CreateSqlBuilderCreateTable(string tableName)
//        {
//            return new CreateTableSqlBuilder_MySql(tableName);
//        }

//        private static Table CreateTableInfoWithForeignKey(out Table referencedTableInfo)
//        {
//            Table tableInfo = CreateTableInfo();
//            AddForeignKeyToTableInfoForeignKey(tableInfo, out referencedTableInfo);
//            return tableInfo;
//        }

//        private static Table CreateTableInfo()
//        {
//            Table tableInfo = new Table {TableName = "TestTable", PrimaryKey = new DBPrimaryKey()};
//            Column pkColumn = new Column("IDColumn") { DataType = "CHAR(38)", Nullable = false};
//            tableInfo.Columns.Add(pkColumn);
//            tableInfo.PrimaryKey.PrimaryKeyColumns.Add(new DBPrimaryKeyColumn { Column = pkColumn });
//            Column columnInfo = new Column("TestColumn") { DataType = "VARCHAR(50)" };
//            tableInfo.Columns.Add(columnInfo);
//            DBKey info = new DBKey();
//            info.KeyName = "TestKey";
//            info.AddColumnInfo(columnInfo);
//            tableInfo.Keys.Add(info);
//            return tableInfo;
//        }

//        private static void AddForeignKeyToTableInfoForeignKey(Table tableInfo, out Table referencedTableInfo)
//        {

//            Column fkColumn = new Column("ForeignKeyColumn") { DataType = "VARCHAR(50)" };
//            tableInfo.Columns.Add(fkColumn);

//            referencedTableInfo = CreateReferencedTableInfo();
//            Column referencedPkColumn = referencedTableInfo.PrimaryKey.PrimaryKeyColumns[0].Column;
//            referencedPkColumn.DataType = "VARCHAR(50)";
//            DBForeignKey foreignKeyInfo = new DBForeignKey
//                                                {
//                                                    ForeignKeyName = "ForeignKey",
//                                                    ParentTable = tableInfo,
//                                                    RelatedTable = referencedTableInfo
//                                                };
//            foreignKeyInfo.ForeignKeyColumns.Add(new DBForeignKeyColumn { ParentColumn = fkColumn, RelatedColumn = referencedPkColumn });

//            foreignKeyInfo.ForeignKeyColumns.Add();
//            tableInfo.ForeignKeys.Add(foreignKeyInfo);
//        }

//        private static Table CreateReferencedTableInfo()
//        {
//            Table referencedTableInfo = new Table("RefTable") { PrimaryKey = new DBPrimaryKey() };
//            Column referencedPkColumn = new Column("IDColumn") { DataType = "CHAR(38)",Nullable = false};
//            referencedTableInfo.Columns.Add(referencedPkColumn);
//            referencedTableInfo.PrimaryKey.PrimaryKeyColumns.Add(new DBPrimaryKeyColumn { Column = referencedPkColumn });
//            return referencedTableInfo;
//        }

//        private void CreateTableWithForeignKey_CreateReferencedTable()
//        {
//            IDbConnection connection = CreateTestDBConnection();
//            Table referencedTableInfo;
//            Table tableInfo = CreateTableInfoWithForeignKey(out referencedTableInfo);
//            DropTable(connection, tableInfo.TableName);
//            CreateTableInDatabase(referencedTableInfo, connection);
//            CreateTableInDatabase(tableInfo, connection);
//        }
//
//        private void CreateTableInDatabase(Table referencedTableInfo, IDbConnection connection)
//        {
//            DatabaseScriptCreator databaseScriptCreator = new DatabaseScriptCreator();
//            string sqlRelatedTable = databaseScriptCreator.CreateTable(referencedTableInfo, GetSqlBuilderCreateTable(referencedTableInfo));
//            DropTable(connection, referencedTableInfo.TableName);
//            _testUtilsDb.ExecuteSql(connection, sqlRelatedTable);
//        }
//
//        protected virtual CreateTableSqlBuilder_MySql GetSqlBuilderCreateTable(Table referencedTableInfo)
//        {
//            return new CreateTableSqlBuilder_MySql(referencedTableInfo.TableName);
//        }

        #endregion

        #region Custom Assertions

        private static void AssertContainsColumns(DataTable expected, DataTable actual)
        {
            List<string> missingColumns = new List<string>(3);
            foreach (DataColumn dataColumn in expected.Columns)
            {
                if (!actual.Columns.Contains(dataColumn.ColumnName))
                {
                    missingColumns.Add(dataColumn.ColumnName);
                }
            }
            if (missingColumns.Count <= 0) return;
            string columns = String.Join(", ", missingColumns.ToArray());
            Assert.Fail("Columns missing from DataTable: " + columns);
        }

        #endregion //Custom Assertions

        #region Test DataTables Validate Structure
        
        private static string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }
        [Test]
        public virtual void Test_GetDatabasesDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            string randomCatalogName = GetRandomString();
            string randomSchemaName = GetRandomString();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetDatabasesDataTable(randomCatalogName, randomSchemaName);
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetDatabasesDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        [Test]
        public void Test_GetDataTypesDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetDataTypesDataTable();
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetDataTypesDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        [Test]
        public void Test_GetTablesDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetTablesDataTable();
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetTablesDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        [Test]
        public void Test_GetColumnsDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetColumnsDataTable(null);
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetColumnsDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        [Test]
        public void Test_GetPrimaryKeyColumnsDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetPrimaryKeyColumnsDataTable(null);
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetPrimaryKeyColumnsDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        [Test]
        public void Test_GetUniqueKeyColumnsDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetUniqueKeyColumnsDataTable(null);
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetUniqueKeyColumnsDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        //KEY_CATALOG, KEY_SCHEMA, KEY_NAME, REFERENCED_TABLE_CATALOG, REFERENCED_TABLE_SCHEMA, REFERENCED_TABLE_NAME
        //SQLSERVER: CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME
        [Test]
        public void Test_GetForeignKeyColumnsDataTable_ValidateDataTable()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetForeignKeyColumnsDataTable(null, null);
            //---------------Test Result -----------------------
            DataTable expectedDataTableTemplate = DBSchemaBuilder.GetForeignKeyColumnsDataTable();
            AssertContainsColumns(expectedDataTableTemplate, dataTable);
        }

        #endregion //Test DataTables Validate Structure
        
        #region Test DataTables Return Correct Rows

        // --------------------------- Has Rows ----------------------------------

        [Test]
        public void Test_GetDatabasesDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetDatabasesDataTable(_testUtilsDb.TestDatabaseName);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, dataTable.Rows.Count);
        }

        [Test]
        public void Test_GetDataTypesDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetDataTypesDataTable();
            //---------------Test Result -----------------------
            Assert.AreNotEqual(0, dataTable.Rows.Count);
        }

        [Test]
        public void Test_GetTablesDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetTablesDataTable();
            //---------------Test Result -----------------------
            Assert.AreEqual(7, dataTable.Rows.Count);
            AssertTableDetailsInDataTable(dataTable, _testPack.ParentDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.ChildDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.UniqueKeyDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.NoPrimaryKeyDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.ManyDataTypesDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.CompositePKDBTable);
            AssertTableDetailsInDataTable(dataTable, _testPack.CompositeFKDBTable);
        }

        private static void AssertTableDetailsInDataTable(DataTable dataTable, DBTable dbTable)
        {
            string tableName = dbTable.TableName;
            DataRow row = TestUtilsDataTable.GetRow(dataTable, DBSchemaTemplate.Naming.TableName, tableName);
            Assert.IsNotNull(row, string.Format("Table '{0}' not found in the DataTable.", tableName));
            //Assert.AreEqual(dbTable.TableType, DBUtilities.ConvertDBToString(row[DBSchemaTemplate.Naming.TableType]));
        }

        private static void AssertAllTableColumnsInDataTable(DataTable dataTable, DBTable dbTable)
        {
            foreach (DBColumn columnInfo in dbTable.Columns)
            {
                AssertColumnDetailsInDataTable(dataTable, columnInfo);
            }
        }
        private static void AssertColumnDetailsInDataTable(DataTable dataTable, DBColumn dbColumn)
        {
            string columnName = dbColumn.ColumnName;
            string tableName = dbColumn.Table.TableName;
            DataRow row = TestUtilsDataTable.GetRow(dataTable, 
                                                new KeyValuePair<string, string>(DBSchemaTemplate.Naming.TableName, tableName),
                                                new KeyValuePair<string, string>(DBSchemaTemplate.Naming.ColumnName, columnName));
            Assert.IsNotNull(row, string.Format("Column '{0}' not found in the DataTable.", columnName));
            string errorMessage = string.Format("Error with column '{0}' of table '{1}'", columnName, tableName );
            //TODO: Fix data type
            //Assert.AreEqual(dbColumn.DataType, DBUtilities.ConvertDBToString(row[DBSchemaTemplate.Naming.DataType]));
            Assert.AreEqual(dbColumn.Nullable, DBUtilities.ConvertDBToBoolean(row[DBSchemaTemplate.Naming.ColumnIsNullable]), errorMessage);
            Assert.AreEqual(dbColumn.IsAutoIncrementing, DBUtilities.ConvertDBToBoolean(row[DBSchemaTemplate.Naming.ColumnIsAutoIncrement]), errorMessage);
            Assert.AreEqual(dbColumn.OrdinalPosition, DBUtilities.ConvertDBToInt(row[DBSchemaTemplate.Naming.OrdinalPosition]), errorMessage);
        }

        [Test]
        public void Test_GetColumnsDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetColumnsDataTable(null);
            //---------------Test Result -----------------------
            Assert.AreEqual(18, dataTable.Rows.Count);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.ParentDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.ChildDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.UniqueKeyDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.NoPrimaryKeyDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.ManyDataTypesDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.CompositePKDBTable);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.CompositeFKDBTable);
        }

        [Test]
        public void Test_GetColumnsDataTable_HasRows_Filtered()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetColumnsDataTable(_testPack.ParentDBTable.TableName);
            //---------------Test Result -----------------------
            Assert.AreEqual(_testPack.ParentDBTable.Columns.Count, dataTable.Rows.Count);
            AssertAllTableColumnsInDataTable(dataTable, _testPack.ParentDBTable);
        }

        [Test]
        public void Test_GetPrimaryKeysDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetPrimaryKeyColumnsDataTable(null);
            //---------------Test Result -----------------------
            Assert.AreEqual(7, dataTable.Rows.Count);
        }

        [Test]
        public void Test_GetUniqueKeysDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetUniqueKeyColumnsDataTable(null);
            //---------------Test Result -----------------------
            Assert.AreEqual(4, dataTable.Rows.Count);
        }

        [Test]
        public void Test_GetForeignKeyColumnsDataTable_HasRows()
        {
            //---------------Set up test pack-------------------
            DBSchemaExtractor dbSchemaExtractor = CreateDBSchemaExtractor();
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            DataTable dataTable = dbSchemaExtractor.GetForeignKeyColumnsDataTable(null, null);
            //---------------Test Result -----------------------
            Assert.AreNotEqual(0, dataTable.Rows.Count);
        }

        #endregion //Test DataTables Returns Correct Number of Rows
        
//        [Ignore()]
//        public class TestDBSchemaExtractor_Oracle : TestDBSchemaExtractor
//        {
//            protected override TestUtilsDB CreateSchemaTestDbUtil()
//            {
//                return new SchemaTestDbUtilOracle();
//            }

//            protected override DBSchemaExtractor CreateDBSchemaExtractor()
//            {
//                return new DBSchemaExtractorOracle(CreateTestDBConnection());
//            }

////            protected override CreateTableSqlBuilder_MySql CreateSqlBuilderCreateTable(string tableName)
////            {
////                return new SqlBuilderCreateTableOracle(tableName);
////            }

////            protected override IDbConnection CreateDBConnection()
////            {
//////                return CreateMasterDBConnection();
////                DatabaseConfig databaseConfig = new DatabaseConfig("SqlServer", "localhost", _testDatabaseName, "sa", "sa", null);
////                IDatabaseConnection databaseConnection = databaseConfig.GetDatabaseConnection();
////                return databaseConnection.GetConnection();
////            }

////            protected override IDbConnection CreateMasterDBConnection()
////            {
////                DatabaseConfig databaseConfig = new DatabaseConfig("SqlServer", "localhost", "master", "sa", "sa", null);
////                IDatabaseConnection databaseConnection = databaseConfig.GetDatabaseConnection();
////                return databaseConnection.GetConnection();
////            }

////            protected override void SetupTestDataBase()
////            {
////                CreateTestDatabase();
////            }

//            protected override void DropTable(IDbConnection connection, string tableName)
//            {
////                ExecuteSql(connection, "IF EXISTS " + referencedTableInfo.TableName + " DROP TABLE " + referencedTableInfo.TableName + "1");
//                try
//                {
//                    _testUtilsDb.ExecuteSql(connection, " DROP TABLE " + tableName);
//                }
//                catch (Exception ex)
//                {
//                    Console.WriteLine(ex);
////                    connection.Close();
////                    connection.Open();
//                }
//            }

////            protected override void CreateTestDatabase()
////            {

////                try
////                {
////                    IDbConnection connection = CreateMasterDBConnection();
////                    if (connection.State == ConnectionState.Closed) connection.Open();
////                    IDbCommand command = connection.CreateCommand();
////                    //

////                        string sqlStatement = string.Format(@"
////                        USE {0};
////        
////                        declare @sql varchar(1024)
////                        declare curs cursor for
////                        select 'ALTER TABLE '+tab.name+' DROP CONSTRAINT '+cons.name
////                        from sys.objects cons,sys.objects tab
////                        where cons.type in ('C', 'F', 'PK', 'UQ', 'D')
////                        and cons.parent_object_id=tab.object_id and tab.type='U'
////                        order by cons.type
////        
////                        open curs
////                        fetch next from curs into @sql
////                        while (@@fetch_status = 0)
////                        begin
////                        exec(@sql)
////                        fetch next from curs into @sql
////                        end
////                        close curs
////                        deallocate curs;
////        
////                        EXEC sp_MSForEachTable 'DROP TABLE ?';
////                        ", _testDatabaseName);

////                        try
////                        {
////                            command.CommandText = sqlStatement;
////                            command.ExecuteNonQuery();
//////                            databaseConnection.ExecuteRawSql(sqlStatement);
////                        }
////                        catch (Exception ex)
////                        {
////                            Console.WriteLine(ex);
////                        }

////                        command.CommandText = string.Format(@"CREATE DATABASE [{0}]", _testDatabaseName);
////                        command.ExecuteNonQuery();
////                }
////                catch (Exception ex)
////                {
////                    Console.WriteLine(ex);
////                }
////            }

////            protected override CreateTableSqlBuilder_MySql GetSqlBuilderCreateTable(Table referencedTableInfo)
////            {
////                return new SqlBuilderCreateTableOracle(referencedTableInfo.TableName);
////            }
//        }
    }

    

   


    internal class DBSchemaExtractorOracle : DBSchemaExtractor
    {
        public DBSchemaExtractorOracle(IDbConnection dbConnection) : base(dbConnection)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the current Catalog Name from the database connection.
        /// </summary>
        public override string CatalogName
        {
            get { throw new System.NotImplementedException(); }
        }

        /// <summary>
        /// Gets the current Schema Name from the database connection.
        /// </summary>
        public override string SchemaName
        {
            get { throw new System.NotImplementedException(); }
        }

        public override DataTable GetDatabasesDataTable(string catalogName, string schemaName)
        {
            throw new System.NotImplementedException();
        }

        protected override DbDataAdapter CreateDataAdapter(string sql)
        {
            throw new NotImplementedException();
        }
    }
/*
    internal class SqlBuilderCreateTableOracle : CreateTableSqlBuilder_MySql
    {
        public SqlBuilderCreateTableOracle(string tableName) : base(tableName)
        {
            throw new NotImplementedException();
        }
    }*/

//    internal class SchemaTestDbUtilOracle : TestUtilsDB
//    {
//        private new const string TestDatabaseName = "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = CORE1)(PORT = 1521)))(CONNECT_DATA = (SERVICE_NAME = XE)))";
//        private const string schemaName = "SCHEMAINFO_TEST";

//        public override DatabaseConfig CreateTestDatabaseConfig()
//        {
//            return new DatabaseConfig("Oracle", "core1", TestDatabaseName, schemaName, schemaName, null);
//        }

//        public override CreateTableSqlBuilder_MySql CreateSqlBuilderCreateTable(string tableName)
//        {
//            throw new System.NotImplementedException();
//        }

//        public override void CreateTestDatabase()
//        {
//            DatabaseConfig databaseConfig = new DatabaseConfig("Oracle", "core1", TestDatabaseName, "HAGASHEN", "HAGASHEN", null);
//            IDatabaseConnection databaseConnection = databaseConfig.GetDatabaseConnection();
//            IDbConnection connection = databaseConnection.GetConnection();
//            if (connection.State == ConnectionState.Closed) connection.Open();
//            string createTableSql = string.Format(@"
//                declare UserCount number;
//                begin
//                select count(*) into UserCount from dba_users where UserName = '{0}';
//                if UserCount = 0 then
//                execute immediate
//                'CREATE USER ' || '{0} IDENTIFIED BY {0}';
//                end if;
//                end;
//                ", schemaName);
//            ExecuteSql(connection, createTableSql);
//        }

//        public override void ClearDatabase(IDbConnection connection)
//        {
//            throw new System.NotImplementedException();
//        }
//    }

    public class DBSchemaExtractorStub : DBSchemaExtractor
    {
        public DBSchemaExtractorStub(IDbConnection idbConnection) : base(idbConnection)
        {
        }

        public override string SchemaName
        {
            get { throw new NotImplementedException(); }
        }

        protected override DbDataAdapter CreateDataAdapter(string sql)
        {
            throw new NotImplementedException();
        }

        public override DataTable GetDatabasesDataTable(string catalogName, string schemaName)
        {
            throw new NotImplementedException();
        }
    }
}